<?php
/*
 * 这里的数据是基于原始数据的处理
 * 数据处理清理之后请不要重复使用
 * */
/*
 * 这里的数据是基于原始数据的处理
 * 数据处理清理之后请不要重复使用
 * */
function sortArray($array,$keys='lastintime',$type='SORT_ASC'){
//$array为要排序的数组,$keys为要用来排序的键名,$type默认为升序排序
    if(!isset($array) || empty($array) ) return false;
    $keysvalue = $new_array = array();
    foreach ($array as $k=>$v){
        $keysvalue[$k] = $v[$keys];
    }
    if($type == 'SORT_ASC'){
        asort($keysvalue);
    }else{
        arsort($keysvalue);
    }
    reset($keysvalue);
    foreach ($keysvalue as $k=>$v){
        $new_array[] = $array[$k];
    }
    return $new_array;
}

function DzDataType($type){
    if (! isset($type) ) return false;
    if (!in_array($type, ['a000', 'a001', 'a002'])) return $type;

    $typeArr=array(
        'a000'=>'AP',
        'a001'=>'STA',
        'a002'=>'RF'
    );
    return $typeArr[$type];
}

function DzDataTypeDe($type){
    if (! isset($type) ) return false;
    if (!in_array($type, ['AP', 'STA', 'RF'])) return $type;

    $typeArr=array(
        'AP'=>'a000',
        'STA'=>'a001',
        'RF'=>'a002'
    );
    return $typeArr[$type];
}

/**
 * setNewDeviceInfo 获取设备devid并放入缓存
 * @param $data
 * @param $theRedis
 * @param $theDb
 * @return bool
 * @Created by: xiebaoxin
 * @DateTime: 2018/4/12 10:40
 */
function setNewDeviceInfo($data,$theRedis,$theDb){
    if (empty($data) ) return false;

    $devkey=$data['devkey'];
    $tbid=$data['tbid'];

    $type=DzDataType($data['type']);

    $rdskey= $type."_".$devkey;
    $addintable= 'addin_'.$data['type'];//addin表 tbhistory 方便统计 新老用户使用，以前出现过的就是老用户
    //新增的设备
    if(!$theRedis->exists($rdskey) || !$theRedis->hExists($rdskey,'devid')){
        $theRedis->hMset($rdskey, array('firsttbid'=> $tbid,'firsttime'=>$data['time']));

        if($data['type']=='a002' ) {
            if(!$theDb->has('rfbase',['deviceId'=>$devkey]))
            {
                if($theRedis->hSetNx($rdskey,'newin',1) ) {
                    $theDb->insert('rfbase', ['deviceId' => $devkey, 'status' => 0, 'time' => $data['time']]);
                }
            }

            $dvid = $theDb->get('rfbase', 'Id', ['deviceId' => $devkey]);

        }elseif ($data['type']=='a001' ){
            if(!$theDb->has('stabase',['mac'=>$devkey])){
                if($theRedis->hSetNx($rdskey,'newin',1) ) {
                    $uid=empty($data['dvuid']) ? "0":$data['dvuid'];
                    $theDb->insert('stabase', array('mac' => $devkey, 'status' => 0, 'time' => $data['time'], 'ouid' => $uid));
                }
            }

            $dvid= $theDb->get('stabase','Id', ['mac'=>$devkey]);
        }
        elseif ($data['type']=='a000' )
        {
            if(!$theDb->has('apbase',['deviceId'=>$devkey])){
                if($theRedis->hSetNx($rdskey,'newin',1) ) {
                    $theDb->insert('apbase', ['deviceId' => $devkey, 'status' => 0, 'time' => $data['time']]);
                }
            }
            $dvid = $theDb->get('apbase', 'Id', ['deviceId' => $devkey]);

        }


        $errmsg="+".$type."+";
        echoMsg($errmsg,$theRedis,false,'basedata_echo');

        if(!isset($dvid) || empty($dvid)) return;

        $theRedis->hSetNx($rdskey,'devid',$dvid);


        if(! $theDb->has($addintable, ['devid' => $dvid,"tbid" => $tbid]))
            $theDb->insert($addintable, array('devid' => $dvid,'tbid' => $tbid,'firsttime'=> time()));

        $theRedis->hSet($rdskey,'tbhistory',json_encode([$tbid]));//加载最近1个,初始化历史

    }else
        $dvid= $theRedis->hGet($rdskey,'devid');

    if(!isset($data['time']))
        $data['time']=time();

    $theRedis->hMset($rdskey, array('lasttbid' => $tbid, 'lasttime' => $data['time']));

    if($tbarrhis=$theRedis->hGet($rdskey, 'tbhistory')) {
        $tbarr = json_decode($tbarrhis, true);
        if (!in_array($tbid, $tbarr)) {
            if(! $theDb->has($addintable, ['devid' => $dvid,"tbid" => $tbid])){
                $theDb->insert($addintable, array('devid' => $dvid, 'tbid' => $tbid, 'firsttime' => $data['time']));
            }

            array_push($tbarr,$tbid);
            if(count($tbarr)>100) array_shift($tbarr);
            $theRedis->hSet($rdskey, 'tbhistory', json_encode($tbarr)); //加入历史缓存,保留最新的100个

        }
    }

    return $dvid;

}

/**
 * //设备被探霸测测到的计数统计setDevCount
 * @param $data
 * @param $redis
 * @param $thisdb
 * @param int $timepd
 * @return bool
 * Created by: xiebaoxin
 */
function setDevCount($data,$redis,$thisdb,$timepd=5){
    if(!isset($data['devkey']) || ! $data['tbmac'] || !isset($data['tbid'])) return false;

    $devrkey=$data['type'].".".$data['devkey'] . "." . $data['tbid'] ;
    if(!$redis->exists($devrkey.".DevTbExpired".PRERDS)) {

        $redis->hincrby($data['tbmac'], $data['type'].'.count5',1);//记录5分钟内探测到的总数

        $redis->set($devrkey.".DevTbExpired".PRERDS,$timepd*60);
        $redis->set($data['tbmac'].".TbExpired".PRERDS,$timepd*60);
        $redis->set($data['devkey'].".DevExpired".PRERDS,60*60);
    }
    $redis->hMSet($devrkey,array(
            'tbmac'=>$data['tbmac'],
            'data'=>json_encode($data),
            'rssi'=>$data['rssi'],
            'time'=>isset($data['time'])? $data['time']: time(),
            'flag'=>'on' //在线
            )
        );

    $redis->expire($devrkey.".DevTbExpired".PRERDS,$timepd*60);//5分钟过期
    $redis->expire($data['tbmac'].".TbExpired".PRERDS,($timepd+1)*60); //探霸6分钟没有更新即过期
    $redis->expire($data['devkey'].".DevExpired".PRERDS,60*60); //目标设备1小时没有更新即过期
    //$redis->EXPIREAT($devrkey.".DevTbExpired".PRERDS,isset($data['time'])? strtotime($data['time']):time() + $timepd*60);//5分钟过期这个key将在'1355292000'=2012.12.12过期

    $count=$redis->hincrby($devrkey,'count',1);//探测次数累计
    return $count;
}

/**
 * setExpiredKey    redis过期通知捕获，计数减
 * @param $keydata
 * @param $theRedis
 * @param $theDb
 * @Created by: xiebaoxin
 * @DateTime: 2018/4/12 10:38
 */
function setExpiredKey($keydata,$theRedis,$theDb){
    if(strpos($keydata, PRERDS) == false ) return;//非本地redis的DB库

    $data=$keydata;
//    $theRedis->del($keydata);//主动清除过期健，但对cpu不友好

    if(strpos($data, ".DevTbExpired".PRERDS) !== false){
        $rdsmKey=explode(".DevTbExpired".PRERDS,$data);      //$rdsmKey=$data['type'].".".$data['devkey'] . "." . $data['tbid'] ;
        $ky=$rdsmKey[0];
        $tbmac= $theRedis->hGet($ky,'tbmac');

        $rdkey=explode(".",$ky);
        if (in_array($rdkey[0], ['a000', 'a001', 'a002'])){

            $theRedis->hincrby($tbmac, $rdkey[0] . '.count5', -1);//记录5分钟内探测到的总数

//            $theRedis->del($ky);//清除过期健-redis默认过期清除的2种方式注意
//
//            $type= DzDataType($rdkey[0]);
//            $tbid=$rdkey[2];
//            $devid= $theRedis->hGet($type."_".$rdkey[1],'devid');
//            if($devid){
//                $theDb->update("addin_".$rdkey[0], array('finds' => $theRedis->hGet($ky,'count'), 'lasttime' =>$theRedis->hGet($ky,'time')),array('devid' => $devid, 'tbid' => $tbid));
//            }

            echo "!";
        }

    }
    else if(strpos($data, ".DevExpired".PRERDS) !== false){
        //设备过期 //1小时没有探测到，清除掉
        $rdsKey=explode(".DevExpired".PRERDS,$data);
        $pipe = $theRedis->multi();
        foreach ($pipe->keys('*_'.$rdsKey[0]) as $ky){
            $type=explode("_",$ky)[0];
            delOldRedisDevKey(DzDataTypeDe($type),$ky,$pipe,$theDb);
        }

        $pipe->exec();

    } else if(strpos($data, ".TbExpired".PRERDS) !== false){
        $rdsKey=explode(".TbExpired".PRERDS,$data);
        if(isset($rdsKey[0])){
            setcountinit($rdsKey[0],$theRedis);
            }

        }
}

/**
 * 检查探霸过期，重置计数，在Tcp通知在线状态时执行
 * @param $tbmac
 * @param $redis
 * @param int $timepd
 * @Created by: xiebaoxin
 * @DateTime: 2018/4/12 10:38
 */
function checktbold($tbmac,$redis,$timepd=5){
    $lasttime= $redis->hGet($tbmac,'lastouttime');
    $lasttime=!isset($lasttime)?time():(int)$lasttime;
    if((time()-$lasttime >$timepd*60) ) {
        setcountinit($tbmac,$redis);  //长时间未连接的上来，重置
    }
}

/**
 * 雷达图计数清零初始化
 * @param $tbKey
 * @param $theRedis
 * @Created by: xiebaoxin
 * @DateTime: 2018/4/12 10:37
 */
function setcountinit($tbKey,$theRedis){
    $tbid =$theRedis->hGet($tbKey, 'tbid');
    foreach ($theRedis->keys('*.'.$tbid.'.DevTbExpired'.PRERDS) as $ky){
        $rdkey=explode(".DevTbExpired".PRERDS,$ky);
        $theRedis->del($rdkey[0]);

        $theRedis->del($ky);

    }
    $theRedis->del($tbKey.".TbExpired".PRERDS);

    $theRedis->hMset($tbKey, array(
        'a000.count5'=>0,
        'a001.count5'=>0,
        'a002.count5'=>0
    )); //探霸过期 重置计数归0

}

function getnowacount($datatype,$tbid,$redis){
    $total=0;
    foreach ($redis->keys($datatype.'.*.'.$tbid.".DevTbExpired".PRERDS) as $ky){
        if($ky){
            $total++;
        }

    }
//     $maclist = $thismstdb->select('short_a001',['deviceid','createtime'], ['GROUP' => 'deviceid','ORDER'=>['createtime'=>'DESC'],'createtime[>]' => (time()-5*60),'tbid' =>$tbid]);

    return $total;
}

/**
 * 清除过期的reids历史设备信息健DelRedisHistory
 * @param $prRedis
 * @param $prConn
 * @param int $timepd 默认1小时
 * Created by: xiebaoxin
 */

function delOldRedisDevKey($type,$ky,$prRedis,$prConn){
    $devitem=$prRedis->hGetAll($ky);
    if(!$devitem || !is_array($devitem)) return;
    $devid= $devitem['devid'];

    //清除最后1分钟未保存的记录
    $staytime=$devitem['staytime'];
    if(isset($staytime) && !empty($staytime) && !empty($devid)  && !empty($devitem['stayinfo'])) {
        $tblist = json_decode($devitem['stayinfo'], true);
        if (isset($tblist) && count($tblist) > 0) {

            foreach ($tblist as $k => $v) {
                $insertdt[] = ['tbid' => $k,
                    'deviceid' => $devid,
                    'findcount'=>(int)$v['cnt'],
                    'rssi'=>json_encode($v['rssi']),
                    'kmrssi'=>json_encode($v['kmRssi']),
                    'kmdist'=>json_encode($v['kmdist']),
                    'createtime' => $staytime
                ];

                echo "^";
                $devrkey=$type.".".explode("_",$ky)[1] . "." .$k ;
                if($prRedis->exists($devrkey))
                    $prRedis->del($devrkey);

            }

            $sql = "call tanbabase('".$type."','".json_encode($insertdt)."');";
            $prConn->query($sql);

            if(config('openKF')) {
                //清除相关滤波
                foreach (array_keys($tblist) as $ki) {
                    $devmac = $type == 'a001' ? substr($ky, 3) : substr($ky, 2);

                    if (isset($this->KfRssi[$ki . "_" . $devmac])) {
                        $this->KfRssi[$ki . "_" . $devmac] = null;
                        unset($this->KfRssi[$ki . "_" . $devmac]);
                    }

                }
            }
        }
    }

    //清除dev健值
    $prRedis->del($ky);

}

function microtime_float()
{
//        return  microtime(true);
    list($usec, $sec) = explode(" ", microtime());
    return (float)sprintf('%.0f',(floatval($usec)+floatval($sec))*1000);
//        return ((float)$usec + (float)$sec);
}


function make_randstr($length = 8)
{
    // 密码字符集，可任意添加你需要的字符
    $chars = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
        'i', 'j', 'k', 'l','m', 'n', 'o', 'p', 'q', 'r', 's',
        't', 'u', 'v', 'w', 'x', 'y','z', 'A', 'B', 'C', 'D',
        'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L','M', 'N', 'O',
        'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y','Z',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
    /*, '!',
        '@','#', '$', '%', '^', '&', '*', '(', ')', '-', '_',
        '[', ']', '{', '}', '<', '>', '~', '`', '+', '=', ',',
        '.', ';', ':', '/', '?', '|'*/
    // 在 $chars 中随机取 $length 个数组元素键名
    $keys = array_rand($chars, $length);
    $password = '';
    for($i = 0; $i < $length; $i++)
    {
        // 将 $length 个数组元素连接成字符串
        $password .= $chars[$keys[$i]];
    }
    return $password;
}
/**
* 求两个已知经纬度之间的距离,单位为米
*
 * @param lng1 $ ,lng2 经度
* @param lat1 $ ,lat2 纬度
* @return float 距离，单位米
* @author www.Alixixi.com
*/
function getLbsdistance($lng1, $lat1, $lng2, $lat2) {
    $radLat1 = deg2rad($lat1); //deg2rad()函数将角度转换为弧度
    $radLat2 = deg2rad($lat2);
    $radLng1 = deg2rad($lng1);
    $radLng2 = deg2rad($lng2);
    $a = $radLat1 - $radLat2;
    $b = $radLng1 - $radLng2;
    $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137 * 1000;
    return $s;
}

function getLocationBaselist($param,$thedb,$redis)
{
    if(!isset($param) || empty($param)|| !isset($param['devmac']))
        return  array('errocode'=>1,'errotext'=>'设备参数错误！');

    $arr = [];
    $arr['deviceID'] = $param['devmac'];
    $tbid=$redis->hGet($param['devmac'],'id');

    $loctioninfo=json_decode($redis->hGet($param['devmac'],'location'),true);
    $redsloctioninfo= json_decode($redis->hGet($param['devmac'],'locationBasekust'),true);
    if($loctioninfo && isset($loctioninfo['longitude']) && !empty($loctioninfo['longitude'])) {
         $basejsoninfo = $thedb->get('device_basehome', ['longitude','latitude','hightland','basejson'],['dvid'=>$tbid]);
        /*if($basejsoninfo && !empty($basejsoninfo['basejson'])){
            $distc=getLbsdistance($basejsoninfo['longitude'],$basejsoninfo['latitude'],$loctioninfo['longitude'],$loctioninfo['latitude']);
            if($distc<1000) //1公里范围内的不查询
            {
                echo "---{$param['devmac']} lon:{$loctioninfo['longitude']},lan:{$loctioninfo['latitude']} distance from pre is：{$distc}--\n";
               if($redsloctioninfo)  return $redsloctioninfo;
            }
        }*/

        $tbloction=array("longitude"=>$loctioninfo['longitude'], "latitude"=>$loctioninfo['latitude'], "hightland"=>$loctioninfo['hightland']);
        $thedb->update("device_basehome",$tbloction, ["dvid" => $tbid, "nickname" =>$param['devmac']]);

        $count=0;
        if(!$redis->exists('lbsserch-'.date('m-d'))){
            $redis->set('lbsserch-'.date('m-d'),0);
            $redis->del('lbsserch-'.date('m-d',strtotime("-1 day")));
        }
        else{
            if($count=$redis->get('lbsserch-'.date('m-d'))>99)
                return  array('errocode'=>1,'errotext'=>'今日查询次数超过100次！');
        }

        $arr['location']=$loctioninfo; // 探霸地址
        $arr['today']=date('m-d');
        $arr['time']=time();
        $arr['tdcounts']=$count; // 查询次数

        /*if (intval($result['location']['longitude']) == 0 || intval($result['location']['latitude']) == 0) {
            $result['location'] = [
                'hightland' => '00000000',
                'latitude' => $lbsData['lat'],
                'longitude' => $lbsData['lon'],
                'time' => date('Y-m-d H:i:s'),
            ];
        }*/
        // 获取LBS周边基站
        // $arr['list']= getCellocation($loctioninfo['latitude'],$loctioninfo['longitude'],10);
        $redis->incr('lbsserch-'.date('m-d'));

        /*if(!empty($arr['list'])){
            $thedb->update('device_basehome',['basejson'=>json_encode($arr),'addtime'=>time()],['dvid'=>$tbid]);

            $thedb->insert('device_basehome_log',  $thedb->get('device_basehome', '*',['dvid'=>$tbid]));

            $redis->hSet($param['devmac'],'locationBasekust',json_encode($arr));
        }else{
            return  array('errocode'=>2,'errotext'=>'没有获取到基站位置！');
        }*/

    }else{
        return  array('errocode'=>3,'errotext'=>'无法获取设备位置或设备不支持！');
    }

    return $arr;
}


/**
 * 根据经纬度反查所在位置附近的基站编号
 *
 * @param float $lat 纬度
 * @param float $lon 经度
 * @param int $n 返回基站个数，范围1-10
 * @param int $mnc 选择运营商，-1:全部（默认），0:移动，1:联通，3:电信
 * @param int $r 返回半径r公里范围内的基站，默认值1
 * @param string $coord 输出坐标类型(wgs84/gcj02/bd09)
 * @return array
 */
function getCellocation($lat, $lon, $n = 10, $mnc = -1, $r = 1)
{
    $config = [
        'lat' => $lat,
        'lon' => $lon,
        'n' => $n,
        'mnc' => $mnc,
        'r' => $r
    ];

    $contents = getCurlData('http://api.cellocation.com:81/recell/?' . http_build_query($config));

    foreach ($contents as &$content) {
        $content['address'] = getAddressByLatLon($content['mnc'], $content['lac'], $content['ci']);
    }

    unset($content);

    return $contents;
}

/**
 * 查询全国移动联通电信2G/3G/4G基站位置数据
 *
 * @param int $mnc  mnc网络类型：0移动，1联通(电信对应sid)，十进制
 * @param int $lac 	lac(电信对应nid)，十进制
 * @param int $ci 	cellid(电信对应bid)，十进制
 * @return string
 */
function getAddressByLatLon($mnc, $lac, $ci)
{
    $query = http_build_query([
        'mcc' => 460, // 中国
        'mnc' => $mnc,
        'lac' => $lac,
        'ci' => $ci,
        'output' => 'json', // 返回json数据
    ]);

    $output = getCurlData('http://api.cellocation.com:81/cell/?' . $query);

    if (!empty($output) && isset($output['address'])) return $output['address'];

    return '';
}


function getCurlData($url)
{
    $ch = curl_init($url);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_ENCODING, "gzip");
    $output = curl_exec($ch);
    curl_close($ch);

    return json_decode($output, true) ?: [];
}


